package com.zdgk.core.control.read.modbus.thread;

import cn.hutool.json.JSONUtil;
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.zdgk.core.control.config.ControlConfigInfo;
import com.zdgk.core.control.config.MqttConfigInfo;
import com.zdgk.core.control.forward.modbus.ModbusSlaveConfig;
import com.zdgk.core.control.read.modbus.cache.DeviceRegisterCache;
import com.zdgk.core.control.read.modbus.cache.DeviceRegisterCacheResult;
import com.zdgk.core.mqtt.MqttClientConfig;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ModbusThread implements Runnable {

    private final String TOPIC = "modbus/test";

    private MqttClientConfig mqttClient;
    private ControlConfigInfo controlConfigInfo;
    private ModbusSlaveConfig modbusSlaveConfig;

    protected final ModbusMaster master;
    protected volatile boolean running = true;

    public ModbusThread(ModbusMaster master, ControlConfigInfo controlConfigInfo, MqttClientConfig mqttClient, ModbusSlaveConfig modbusSlaveConfig) {
        this.master = master;
        this.mqttClient = mqttClient;
        this.controlConfigInfo = controlConfigInfo;
        this.modbusSlaveConfig = modbusSlaveConfig;
    }

    public void stop() {
        running = false;
    }

    @Override
    public void run() {
        while (running && master != null && master.isConnected()) {
            try {
                read();
            } catch (Exception e) {
                log.error(e.getMessage());
                reContent();
            } finally {
                try {
                    DeviceRegisterCacheResult.lastTime = new Date();
//                    log.info("最新输入寄存器：{}", DeviceRegisterCache.inputRegisterInfo.toString());
                    try {
                        mqttClient.publishUpload(JSONUtil.toJsonStr(DeviceRegisterCacheResult.ruleValueMap));
                    } catch (Exception e) {
                        log.error("mqtt推送失败");
                    }

                    Thread.sleep(1000 * controlConfigInfo.getSendInterval());
                } catch (InterruptedException e) {
                }
            }
        }
    }

    private void read() throws Exception {
        Integer[] serverAddressArr = controlConfigInfo.getServerAddressArr();
        Integer quantity = controlConfigInfo.getQuantity();
        Integer keepQuantity = controlConfigInfo.getKeepQuantity();
        for (int i = 0; i < serverAddressArr.length; i++) {
            try {
                if (quantity <= 0) {
                    //不读取
                } else if (quantity > 0 && quantity <= 125) {
                    int[] registers = master.readInputRegisters(serverAddressArr[i], controlConfigInfo.getReadStartAddress(), quantity);
                    for (int j = 0; j < registers.length; j++) {
                        DeviceRegisterCache.setInputRegisterInfo(serverAddressArr[i], controlConfigInfo.getReadStartAddress() + j, registers[j]);
                    }
                } else {
                    int f = quantity / 125;
                    int s = quantity % 125;
                    for (int fi = 0; fi < f; fi++) {
                        int[] registers = master.readInputRegisters(serverAddressArr[i], controlConfigInfo.getReadStartAddress() + (fi * (125)), 125);
                        for (int j = 0; j < registers.length; j++) {
                            DeviceRegisterCache.setInputRegisterInfo(serverAddressArr[i], controlConfigInfo.getReadStartAddress() + ((fi * (125)) + j), registers[j]);
                        }
                    }
                    int[] registers_y = master.readInputRegisters(serverAddressArr[i], controlConfigInfo.getReadStartAddress() + (f * (125)), s);
                    for (int jy = 0; jy < registers_y.length; jy++) {
                        DeviceRegisterCache.setInputRegisterInfo(serverAddressArr[i], controlConfigInfo.getReadStartAddress() + ((f * (125)) + jy), registers_y[jy]);
                    }

                }
                if (keepQuantity <= 0) {
                    //不读取
                } else if (keepQuantity > 0 && keepQuantity <= 125) {
                    int[] registers = master.readHoldingRegisters(serverAddressArr[i], controlConfigInfo.getKeepReadStartAddress(), keepQuantity);
                    for (int j = 0; j < registers.length; j++) {
                        DeviceRegisterCache.setKeepRegisterInfo(serverAddressArr[i], controlConfigInfo.getKeepReadStartAddress() + j, registers[j]);
                    }
                } else {
                    int f = keepQuantity / 125;
                    int s = keepQuantity % 125;
                    for (int fi = 0; fi < f; fi++) {
                        int[] registers = master.readHoldingRegisters(serverAddressArr[i], controlConfigInfo.getKeepReadStartAddress() + (fi * (125)), 125);
                        for (int j = 0; j < registers.length; j++) {
                            DeviceRegisterCache.setKeepRegisterInfo(serverAddressArr[i], controlConfigInfo.getKeepReadStartAddress() + ((fi * (125)) + j), registers[j]);
                        }
                    }
                    int[] registers_y = master.readHoldingRegisters(serverAddressArr[i], controlConfigInfo.getKeepReadStartAddress() + (f * (125)), s);
                    for (int jy = 0; jy < registers_y.length; jy++) {
                        DeviceRegisterCache.setKeepRegisterInfo(serverAddressArr[i], controlConfigInfo.getKeepReadStartAddress() + ((f * (125)) + jy), registers_y[jy]);
                    }

                }

            } catch (Exception e) {
                log.error("从站[{}]读取错误,Modbus连接状态：[{}],{}", serverAddressArr[i], master.isConnected(), e.getMessage());
                reContent();
            }
            DeviceRegisterCacheResult.mappingRule(serverAddressArr[i], controlConfigInfo);
        }
        //更新模拟从站
        try{
            modbusSlaveConfig.updateData();
        }catch (Exception e){
            log.error("模拟从站更新失败：{}",e.getMessage());
        }
    }

    private void reContent() {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(() -> {
                try {
                    master.connect();
                    if(master.isConnected()){
                        scheduler.shutdown();  // 任务完成后关闭调度器
                    }
                } catch (Exception e) {
                    System.out.println("Modbus重新连接失败");
                }
        }, 0, 3, TimeUnit.SECONDS);  // 延迟0秒后每3秒执行一次
    }
}
